/**
 *
 */
package tao.data.structure.tree;

import tao.data.structure.tree.Tree;

/**
 * To traverse a tree in In-Order
 * <br><br>
 * 
 * <b> Factor </b><br>
 * The factor which is a parameter passed to constructor control how many subtrees visited
 * before its parent node and hence determined how many subtrees be visited after its parent node be visited.
 * <br>
 * Note that if the factor greater or equal to the number of children node, the behavior of In-Order
 * traversal is same as Post-Order. In contrast, if the factor is less or equal to zero, the 
 * behavior of In-Order traversal is same as Pre-Order
 * 
 * @author Joe Choi
 * @version 1.0.0
 */
class InOrderTraversal<V> 
	extends AbstractTraversal<V> {
	public InOrderTraversal(Tree<V> tree, int factor) {
		super(tree);
		this.factor = (factor < 0 ? 0 : factor);
	}
	
	@Override
	protected void traverse(Tree<V> t) {
		int count = 0;
		
		notifyObserver(new Traversal.Event<V>(Traversal.Event.Type.BeforeTraverseSubtree, t));
		count = (factor > t.getSubtree().size() ? t.getSubtree().size() : factor);
		for(Tree<V> child : t.getSubtree()) {
			if(count == 0) break;
			traverse(child);
			count--;
		}
		
		notifyObserver(new Traversal.Event<V>(Traversal.Event.Type.TraversedTree, t));
		
		count = (factor > t.getSubtree().size() ? t.getSubtree().size() : factor);
		for(Tree<V> child : t.getSubtree()) {
			if((count--) > 0) continue;
			traverse(child);
		}
		notifyObserver(new Traversal.Event<V>(Traversal.Event.Type.AfterTraverseSubtree, t));
	}
	
	private int factor;
	
	/**
	 * To create an new InOrderTraversal
	 */
	static class Factory<V> extends AbstractFactory<V> {
		public Factory(Tree<V> tree, int factor) {
			super(tree);
			this.factor = factor;
		}
		
		@Override
		public Traversal<V> create() {
			return(new InOrderTraversal<V>(getTree(), factor));
		}
		
		private int factor;
	}
}
